package com.geeaks.generator.generator.impl;

import java.io.File;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import com.geeaks.generator.enums.EnumTypeTransfer;
import com.geeaks.generator.enums.PatternConst;
import com.geeaks.generator.generator.Generator;
import com.geeaks.generator.model.RowInfoBo;
import com.geeaks.generator.model.TableInfoBo;
import com.geeaks.generator.util.DbUtil;
import com.geeaks.generator.util.VelocityUtils;
import com.google.common.base.Splitter;
import com.google.common.collect.Maps;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;

public class WubaGenerator extends Generator {
	
	@Override
	protected void renderTemplate(File sourceFile) throws Exception {
		// 目录的话 递归执行
		if (sourceFile.isDirectory()) {
			for (File file : sourceFile.listFiles()) {
				renderTemplate(file);
			}
		} else if (StringUtils.endsWith(sourceFile.getName(), ".vm") || 
				StringUtils.endsWith(sourceFile.getName(), ".origin")) {
			Map<String, Object> fillData = Maps.newHashMap();
			TableInfoBo tableInfo = DbUtil.getTableInfo(dbConfig, config.getTableNameField());
			/******** 渲染entity ********/
			renderEntity(fillData, tableInfo);
			/******** 渲染xml ********/
			renderXml(fillData, tableInfo);
			/******** 渲染dao ********/
			renderMapper(fillData, tableInfo);
			/******** 渲染test ********/
			renderTest(fillData, tableInfo);
			// 表注释
			fillData.put("tableDesc", tableInfo.getTableDesc());
			// entity里的字段
			fillData.put("javaField", config.getPackageNameField());
			fillData.put("tableNameField", config.getTableNameField());
			// 包路径
			fillData.put("package", config.getPackageNameField());
			// 类名
			fillData.put("className", config.getEntityField());
			// 作者
			fillData.put("author", config.getAuthor());
			// 当前日期
			fillData.put("nowDate", DateUtil.now());
			String sourcePath = StringUtils.removeStart(sourceFile.getPath(), prefix);
			String entityField = config.getEntityField();
			if(StringUtils.startsWith(sourceFile.getName(), "Common")) {
				entityField = "";
			}
			String targetPath = null;
			if(StringUtils.endsWith(sourceFile.getName(), ".origin")) {
				targetPath = config.getTargetField() + StringUtils.removeEnd(sourcePath,sourceFile.getName()) + StringUtils.removeEnd(sourceFile.getName(), ".origin");
			} else {
				targetPath = config.getTargetField() + StringUtils.removeEnd(sourcePath,sourceFile.getName()) + entityField + StringUtils.removeEnd(sourceFile.getName(), ".vm");
			}
			
			targetPath = StringUtils.remove(targetPath, "/template/" + config.getTemplatePath());
			targetPath = StringUtils.replace(targetPath, "\\", "/");
			System.err.println(targetPath);
			String packageName = StringUtils.replace(config.getPackageNameField(), ".", "/");
			String searchStr = "src/main/java";
			if(StringUtils.contains(targetPath, "src/main/resources")) {
				searchStr = "src/main/resources";
			} else if(StringUtils.contains(targetPath, "src/test/java")) {
				searchStr = "src/test/java";
			}
			targetPath = StringUtils.replace(targetPath, searchStr, ",");
			List<String> split = Splitter.on(",").splitToList(targetPath);
			if(StringUtils.equalsIgnoreCase(searchStr, "src/main/resources")) {
				targetPath = split.get(0) + searchStr + "/" + split.get(1);
			} else {
				targetPath = split.get(0) + searchStr + "/" + packageName + split.get(1);
			}
			targetPath = StringUtils.replace(targetPath, "template/classic3Layer/src", "");
			targetPath = StringUtils.replace(targetPath, packageName, "");
			FileUtils.write(new File(targetPath), VelocityUtils.getTemplate(sourcePath, fillData), StandardCharsets.UTF_8);
		}
	}
	
	private void renderTest(Map<String, Object> fillData, TableInfoBo tableInfo) {
		StringBuilder fuzhi = new StringBuilder();
		StringBuilder testImport = new StringBuilder();
		String className2 = StrUtil.toCamelCase(config.getTableNameField());
		Map<String, String> importmap = Maps.newHashMap();
		for (RowInfoBo rowInfo : tableInfo.getTableColumns()) {
			String camelCase = StrUtil.toCamelCase(rowInfo.getField());
			String capitalizeCamelCase = StringUtils.capitalize(camelCase);
			EnumTypeTransfer typeTransfer = EnumTypeTransfer.codeOf(rowInfo.getType());
			if (!importmap.containsKey(typeTransfer.javaType2)) {
				importmap.put(typeTransfer.javaType2, "");
				if(typeTransfer.needImport() && !EnumTypeTransfer.Common.equals(typeTransfer))
				testImport.append(StrUtil.format(PatternConst.importPattern, typeTransfer.javaTypeImport));
			}
			String value = "";
			if(typeTransfer.javaType2.equals("Long")) {
				value = RandomUtil.randomNumbers(3)+"L";
			} else if(typeTransfer.javaType2.equals("Integer")
					||typeTransfer.javaType2.equals("Byte")
					||typeTransfer.javaType2.equals("Short")
					) {
				value = "("+typeTransfer.javaType+")"+RandomUtil.randomNumbers(1);
			} else if(typeTransfer.javaType2.equals("Float")) {
				value = RandomUtil.randomDouble()+"f";
			} else if(typeTransfer.javaType2.equals("Double")) {
				value = RandomUtil.randomDouble()+"d";
			} else if(typeTransfer.javaType2.equals("BigDecimal")) {
				value = "new BigDecimal(\""+RandomUtil.randomBigDecimal().toString()+"\")";
			} else if(typeTransfer.javaType2.equals("Date")) {
				value = "new Date()";
			} else if(typeTransfer.javaType2.equals("Timestamp")) {
				value = "new Timestamp(System.currentTimeMillis())";
			} else {
				value = "\""+RandomUtil.randomString(12)+"\"";;
			}
			fuzhi.append("		"+className2+".set"+capitalizeCamelCase+"("+value +");\n");
		}
		fillData.put("fuzhi", fuzhi.toString());
		fillData.put("testImport", testImport.toString());
	}

	private void renderMapper(Map<String, Object> fillData, TableInfoBo tableInfo) {
		StringBuilder importJavaType = new StringBuilder();
		for (RowInfoBo rowInfo : tableInfo.getTableColumns()) {
			EnumTypeTransfer typeTransfer = EnumTypeTransfer.codeOf(rowInfo.getType());
			if("id".equals(rowInfo.getField())) {
				fillData.put("idType", typeTransfer.javaType);
				if(typeTransfer.needImport() && !EnumTypeTransfer.Common.equals(typeTransfer))
				importJavaType.append(StrUtil.format(PatternConst.importPattern, typeTransfer.javaTypeImport));
			}
			fillData.put("daoImport", importJavaType.toString());
			fillData.put("className2", StrUtil.toCamelCase(config.getTableNameField()));
		}
	}
	
	private void renderXml(Map<String, Object> fillData, TableInfoBo tableInfo) {
		StringBuilder column = new StringBuilder();
		StringBuilder selColumn = new StringBuilder();
		StringBuilder whereColumn = new StringBuilder();
		StringBuilder updateColumn = new StringBuilder();
		StringBuilder insertColumn = new StringBuilder();
		boolean hasId = false;
		for (RowInfoBo rowInfo : tableInfo.getTableColumns()) {
			if("id".equals(rowInfo.getField())) {
				hasId = true;
			} else {
				column.append(rowInfo.getField()).append(",");
			}
			String camelCase = StrUtil.toCamelCase(rowInfo.getField());
			if(StrUtil.containsAny(rowInfo.getField(), "_")) {
				selColumn.append(rowInfo.getField() + " " + StrUtil.toCamelCase(rowInfo.getField())).append(",");
			} else {
				selColumn.append(rowInfo.getField()).append(",");
			}
			EnumTypeTransfer typeTransfer = EnumTypeTransfer.codeOf(rowInfo.getType());
			if("create_time".equals(rowInfo.getField()) || "update_time".equals(rowInfo.getField()) ) {
				
			} else {
				if(EnumTypeTransfer.VARCHAR.equals(typeTransfer) || EnumTypeTransfer.CHAR.equals(typeTransfer) || EnumTypeTransfer.Common.equals(typeTransfer)) {
					whereColumn.append(StrUtil.format(PatternConst.wherePattern, camelCase,camelCase,rowInfo.getField(),camelCase));
				} else {
					whereColumn.append(StrUtil.format(PatternConst.wherePattern2, camelCase,rowInfo.getField(),camelCase));
				}
			}
			if("create_time".equals(rowInfo.getField()) || "update_time".equals(rowInfo.getField()) 
				|| "id".equals(rowInfo.getField())) {
//				updateColumn.append(StrUtil.format(PatternConst.updatePattern, camelCase,camelCase,rowInfo.getField(),camelCase));
			} else {
				if(EnumTypeTransfer.VARCHAR.equals(typeTransfer) || EnumTypeTransfer.CHAR.equals(typeTransfer) || EnumTypeTransfer.Common.equals(typeTransfer)) {
					updateColumn.append(StrUtil.format(PatternConst.updatePattern, camelCase,camelCase,rowInfo.getField(),camelCase));
				} else {
					updateColumn.append(StrUtil.format(PatternConst.updatePattern2, camelCase,rowInfo.getField(),camelCase));
				}
			}
			
			if("create_time".equals(rowInfo.getField()) || "update_time".equals(rowInfo.getField()) 
					|| "is_del".equals(rowInfo.getField()) || "id".equals(rowInfo.getField())) {
				if("is_del".equals(rowInfo.getField())) {
					insertColumn.append("0,");
				} else if("create_time".equals(rowInfo.getField()) || "update_time".equals(rowInfo.getField())) {
					insertColumn.append("now(),");
				}
			} else {
				insertColumn.append("#{").append(camelCase).append("},");
			}
		}
		fillData.put("hasId", hasId);
		fillData.put("column", StringUtils.removeEnd(column.toString(), ","));
		fillData.put("selColumn", StringUtils.removeEnd(selColumn.toString(), ","));
		fillData.put("whereColumn", StrUtil.removeSuffix(whereColumn.toString(), "\n"));
		fillData.put("updateColumn", StrUtil.removeSuffix(updateColumn.toString(), "\n"));
		fillData.put("insertColumn", StringUtils.removeEnd(insertColumn.toString(), ","));
	}
	
	private void renderEntity(Map<String, Object> fillData, TableInfoBo tableInfo) {
		StringBuilder importJavaType = new StringBuilder();
		StringBuilder fields = new StringBuilder();
		Map<String, String> importmap = Maps.newHashMap();
		int i=1;
		for (RowInfoBo rowInfo : tableInfo.getTableColumns()) {
			EnumTypeTransfer typeTransfer = EnumTypeTransfer.codeOf(rowInfo.getType());
			if (!importmap.containsKey(typeTransfer.javaType)) {
				importmap.put(typeTransfer.javaType, "");
				if(typeTransfer.needImport() && !EnumTypeTransfer.Common.equals(typeTransfer))
				importJavaType.append(StrUtil.format(PatternConst.importPattern, typeTransfer.javaTypeImport));
			}
			String camelCase = StrUtil.toCamelCase(rowInfo.getField());
			fields.append(StrUtil.format(PatternConst.entityFieldPattern, rowInfo.getComment(), i++,typeTransfer.javaType, camelCase));
		}
		fillData.put("fields", StrUtil.removeSuffix(fields.toString(), "\n"));
		fillData.put("importJavaType", StrUtil.removeSuffix(importJavaType.toString(), "\n"));
	}
	
}
